package org.jeecg.modules.awpay.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.*;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.gson.internal.$Gson$Preconditions;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.log.Log;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.modules.alipay.bo.PaymentBO;
import org.jeecg.modules.awpay.common.request.*;
import org.jeecg.modules.awpay.common.result.*;
import org.jeecg.modules.awpay.dao.entity.AlipayNotifyParam;
import org.jeecg.modules.awpay.service.AliPayService;
import org.jeecg.modules.gwcjava.jiekou.entity.*;
import org.jeecg.modules.gwcjava.jiekou.service.BusinessLogicService;
import org.jeecg.modules.gwcjava.jiekou.service.MlccUserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.schema.Entry;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


/**
 *  支付宝支付，控制器
 *
 * @author wangziyang
 * */
@Api(tags="后台支付控制器")
@RestController
@RequestMapping("/ali/pay")
@Slf4j
public class AlipayController {
    @Autowired
    private AliPayService aliPayService;
    /**查询用户信息*/
    @Autowired
    private MlccUserInfoService userservice;
    @Autowired
    private BusinessLogicService logicService;

    //线程
    private ExecutorService executorService = Executors.newFixedThreadPool(20);

    /**
     * 确认支付订单
     * @param
     * @return boolean
     */
    @PostMapping(value = "/order/create")
    @ResponseBody
    @Transactional(rollbackFor = Exception.class)
    public Result<AlipayTradePagePayResponse> create(OrderCreateRequest request)  {
//        try {
            MlccUserInfo userInfo = userservice.queryUserinfoByusername(request.getToken(),3);
            if(userInfo==null){
                return Result.error(-1,"token失效，请重新登录");
            }
            if(request.getOrderSn()==null || "".equals(request.getOrderSn())){
                return Result.error(-1,"订单编号不能为空");
            }
            if("0".equals(request.getOrderType())){
                request.setOrderName("面料下单");
                request.setSubject("面料下单");
                request.setBody("铭朗云服装定制面料下单");
                PaymentBO paymentBO = logicService.query_paymentBODetail(request.getOrderSn(),request.getOrderType());
                if(paymentBO!=null){
                    request.setPayChannel("ALIPAY_PC");
                    request.setOrderMoney(paymentBO.getOrderMoney());
                    request.setPayAmount(paymentBO.getOrderMoney());
                    request.setOrderSn(request.getOrderSn());
                    return aliPayService.create(request);
                }else {
                    return Result.error(-1,"下单失败");
                }
            }else if("1".equals(request.getOrderType())){
                request.setOrderName("个订下单");
                request.setSubject("个订下单");
                request.setBody("铭朗云服装定制个订下单");
                PaymentBO paymentBO = logicService.query_paymentBODetail(request.getOrderSn(),request.getOrderType());
                if(paymentBO!=null){
                    request.setPayChannel("ALIPAY_PC");
                    request.setOrderMoney(paymentBO.getOrderMoney());
                    request.setPayAmount(paymentBO.getOrderMoney());
                    request.setOrderSn(request.getOrderSn());
                    return aliPayService.create(request);
                }else {
                    return Result.error(-1,"下单失败");
                }
            }else if("2".equals(request.getOrderType())){
                request.setOrderName("团订下单");
                request.setSubject("团订下单");
                request.setBody("铭朗云服装定制团订下单");
                PaymentBO paymentBO = logicService.query_paymentBODetail(request.getOrderSn(),request.getOrderType());
                if(paymentBO!=null){
                    request.setPayChannel("ALIPAY_PC");
                    request.setOrderMoney(paymentBO.getOrderMoney());
                    request.setPayAmount(paymentBO.getOrderMoney());
                    request.setOrderSn(request.getOrderSn());
                    return aliPayService.create(request);
                }else {
                    return Result.error(-1,"下单失败");
                }
            }else if("3".equals(request.getOrderType())){
                //8位随机数
                int random=new Random().nextInt(100000)+1;//为变量赋随机值1-99999999;
                //先创建充值订单
                Long startTs = System.currentTimeMillis(); // 当前时间戳
                String charge_sn = "CHRAG"+startTs+random;
                ChargeOrderInfo chargeOrderInfo = new ChargeOrderInfo();
                chargeOrderInfo.setChargeSn(charge_sn);
                chargeOrderInfo.setApplyMethod(request.getApplyMethod());
                chargeOrderInfo.setUserId(userInfo.getId().toString());
                chargeOrderInfo.setMoney(request.getOrderSn());
                chargeOrderInfo.setStatus(0);//假设充值成功
                userservice.create_chargeOrder(chargeOrderInfo);
                request.setOrderName("用户余额充值");
                request.setSubject("用户余额充值");
                request.setBody("铭朗云用户余额充值订单");
                request.setPayChannel("ALIPAY_PC");
                request.setOrderMoney(request.getOrderSn());
                request.setPayAmount(request.getOrderSn());
                request.setOrderSn(charge_sn);
                return aliPayService.create(request);
            }
            else {
                return Result.error(-1,"请传入订单类型");
            }
//        }catch (Exception e){
//            return Result.error(-1,"失败="+e);
//        }
    }


    @ResponseBody
    @RequestMapping(value = "/order/query",method = RequestMethod.POST)
    public Result<AlipayTradeQueryResponse> query(@RequestBody OrderQueryRequest request)  {
        if(StringUtils.isEmpty(request.getOutTradeNo())){
            return Result.error(-1,"outTradeNo不能为空");
        }
        return aliPayService.query(request);
    }

    @ResponseBody
    @RequestMapping(value = "/ali/pay/order/close",method = RequestMethod.POST)
    public Result<AlipayTradeCloseResponse> close(@RequestBody OrderCloseRequest request)  {

        if(StringUtils.isEmpty(request.getOutTradeNo())){
            return Result.error(-1,"outTradeNo不能为空");
        }

        return aliPayService.close(request);
    }

    @ResponseBody
    @RequestMapping(value = "/order/refund",method = RequestMethod.POST)
    public Result<AlipayTradeRefundResponse> query(@RequestBody OrderRefundRequest request)  {

        if(StringUtils.isEmpty(request.getOutTradeNo())){
            return Result.error(-1,"outTradeNo不能为空");
        }

        if(StringUtils.isEmpty(request.getPayAmount())){
            return Result.error(-1,"payAmount不能为空");
        }

        if(StringUtils.isEmpty(request.getRefundAmount())){
            return Result.error(-1,"refundAmount不能为空");
        }

        if(StringUtils.isEmpty(request.getRefundReason())){
            return Result.error(-1,"refundReason不能为空");
        }

        String outRefundNo = "R" + IdWorker.getId();
        request.setOutRefundNo(outRefundNo);

        return aliPayService.refund(request);
    }

    @ResponseBody
    @RequestMapping(value = "/refund/query",method = RequestMethod.POST)
    public Result<AlipayTradeFastpayRefundQueryResponse> query(@RequestBody RefundQueryRequest request)  {

        if(StringUtils.isEmpty(request.getOutTradeNo())){
            return Result.error(-1,"outTradeNo不能为空");
        }

        return aliPayService.refundQuery(request);
    }

    /**
     * 支付成功的回调地址
     * @return
     */
    @PostMapping(value = "/fallback")
    @Transactional(rollbackFor = Exception.class)
    public String fallback(HttpServletRequest request){
        Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        String paramsJson = JSON.toJSONString(params);
//        System.out.println("回调过来的数据=="+params.get("out_trade_no")+"==="+params.get("subject"));
        try {
            // 调用SDK验证签名
            boolean signVerified = AlipaySignature.rsaCheckV1(params, CommonConstant.ZFB_sign_KEY,
                    "utf-8", "RSA2");
            if (signVerified) {
                System.out.println("支付宝回调签名认证成功");
                // 按照支付结果异步通知中的描述，对支付结果中的业务内容进行1\2\3\4二次校验，校验成功后在response中返回success，校验失败返回failure
//                this.check(params);
                // 另起线程处理业务
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        AlipayNotifyParam param = buildAlipayNotifyParam(params);
                        String trade_status = param.getTradeStatus();
                        // 支付成功
                        if (trade_status.equals("TRADE_SUCCESS")) {
                            // 处理支付成功逻辑
                            try {
                                //拿到回调后的订单编号
                                String out_trade_no = params.get("out_trade_no").toString();
                                String subject = params.get("subject").toString();
                                //订单类型type:0面料，1个订，2团订，3成衣
                                if("个订下单".equals(subject)){
                                    //根据订单编号查询订单信息
                                    SingleOrderInfo singleOrderInfo = logicService.query_signorder(out_trade_no);
                                    if(singleOrderInfo!=null) {
                                        if (singleOrderInfo.getStatus() == 11) {
                                            Long startTs = System.currentTimeMillis(); // 当前时间戳
                                            //8位随机数
                                            int random = new Random().nextInt(1000000) + 1;//为变量赋随机值1-99999999;
                                            String category_code = startTs.toString() + random;//流水id
                                            String genzong_id = "GZB" + startTs.toString() + random;//跟踪id
                                            String event_id = "EVENT" + startTs.toString() + random;//事件id
                                            //执行修改个订单的业务
                                            logicService.change_order_status(out_trade_no, 1,0);
                                            //第二部-插入流水表
                                            BusinessWaterInfo datainfo = new BusinessWaterInfo();
                                            datainfo.setId(category_code);
                                            datainfo.setYewuDeatil("个订下单");
                                            datainfo.setOrderId(singleOrderInfo.getId().toString());
                                            datainfo.setCostMoney(singleOrderInfo.getOrderMoney());
                                            datainfo.setOrderSn(out_trade_no);
                                            datainfo.setRemark("个订订单");
                                            datainfo.setYewuInstructions("个订下单");
                                            datainfo.setUserId(singleOrderInfo.getUserId());
                                            datainfo.setStoreId(singleOrderInfo.getStoreId());
                                            datainfo.setApplyMethod(1);
                                            datainfo.setStatus(2);
                                            datainfo.setType(1);
                                            datainfo.setSysOrgCode(singleOrderInfo.getSysOrgCode());
                                            logicService.insert_into_water(datainfo);
                                            //第三部-插入订单跟踪表
                                            logicService.insert_into_ordertracking(genzong_id, out_trade_no, "1", "个订订单在线支付", "支付宝在线支付", 1);
                                            //第四部-插入订单事件表
                                            logicService.insert_into_orderevent(event_id, "你有一条新的个订订单", 0, out_trade_no, "1", "你有一条新的个订订单");
                                        }
                                    }
                                }else if("面料下单".equals(subject)){
                                    FabricOrderInfo fabricOrderInfo = logicService.query_fabricOrderDetailBycode(out_trade_no);
                                    if(fabricOrderInfo!=null) {
                                        if (fabricOrderInfo.getStatus() == 0) {
                                            Long startTs = System.currentTimeMillis(); // 当前时间戳
                                            //8位随机数
                                            int random = new Random().nextInt(100000) + 1;//为变量赋随机值1-99999999;
                                            String category_code = startTs.toString() + random;//流水id
                                            String genzong_id = "GZB" + startTs.toString() + random;//跟踪id
                                            String event_id = "EVENT" + startTs.toString() + random;//事件id
                                            //执行修改面料订单的业务
                                            logicService.change_order_status(out_trade_no, 0,0);
                                            //第二部-插入流水表
                                            BusinessWaterInfo datainfo = new BusinessWaterInfo();
                                            datainfo.setId(category_code);
                                            datainfo.setYewuDeatil("面料订单");
                                            datainfo.setOrderId(fabricOrderInfo.getId().toString());
                                            datainfo.setCostMoney(fabricOrderInfo.getOrderMoney());
                                            datainfo.setOrderSn(out_trade_no);
                                            datainfo.setRemark("面料订单");
                                            datainfo.setYewuInstructions("面料下单");
                                            datainfo.setUserId(fabricOrderInfo.getUserId());
                                            datainfo.setStoreId(fabricOrderInfo.getStoreId());
                                            datainfo.setApplyMethod(1);
                                            datainfo.setStatus(2);
                                            datainfo.setType(0);
                                            datainfo.setSysOrgCode(fabricOrderInfo.getSysOrgCode());
                                            logicService.insert_into_water(datainfo);
                                            //第三部-插入订单跟踪表
                                            logicService.insert_into_ordertracking(genzong_id, out_trade_no, "0", "面料订单在线支付", "支付宝在线支付", 1);
                                            //第四部-插入订单事件表
                                            logicService.insert_into_orderevent(event_id, "你有一条新的面料订单", 0, out_trade_no, "0", "你有一条新的面料订单");
                                        }
                                    }
                                }else if("团订下单".equals(subject)){
                                    TeamOrderInfo fabricOrderInfo = logicService.queryOrderDetail(out_trade_no);
                                    if(fabricOrderInfo!=null) {
                                        if (fabricOrderInfo.getStatus() == 11) {
                                            Long startTs = System.currentTimeMillis(); // 当前时间戳
                                            //8位随机数
                                            int random = new Random().nextInt(10000) + 1;//为变量赋随机值1-99999999;
                                            String category_code = startTs.toString() + random;//流水id
                                            String genzong_id = "GZB" + startTs.toString() + random;//跟踪id
                                            String event_id = "EVENT" + startTs.toString() + random;//事件id
                                            //执行修改团订订单的业务
                                            logicService.change_order_status(out_trade_no, 2,0);
                                            //第二部-插入流水表
                                            BusinessWaterInfo datainfo = new BusinessWaterInfo();
                                            datainfo.setId(category_code);
                                            datainfo.setYewuDeatil("团订订单");
                                            datainfo.setOrderId(fabricOrderInfo.getId().toString());
                                            datainfo.setCostMoney(fabricOrderInfo.getOrderMoney());
                                            datainfo.setOrderSn(out_trade_no);
                                            datainfo.setRemark("团订订单");
                                            datainfo.setYewuInstructions("团订下单");
                                            datainfo.setUserId(fabricOrderInfo.getUserId());
                                            datainfo.setStoreId(fabricOrderInfo.getStoreId());
                                            datainfo.setApplyMethod(1);
                                            datainfo.setStatus(2);
                                            datainfo.setType(2);
                                            datainfo.setSysOrgCode(fabricOrderInfo.getSysOrgCode());
                                            logicService.insert_into_water(datainfo);
                                            //第三部-插入订单跟踪表
                                            logicService.insert_into_ordertracking(genzong_id, out_trade_no, "2", "团订订单在线支付", "支付宝在线支付", 1);
                                            //第四部-插入订单事件表
                                            logicService.insert_into_orderevent(event_id, "你有一条新的团订订单", 0, out_trade_no, "2", "你有一条新的团订订单");
                                        }
                                    }
                                }else {
                                    //根据充值订单流水号查询（已充值就修改用户余额）
                                    ChargeOrderInfo datainfoDetail = userservice.queryChargeOrderInfo(out_trade_no);
                                    String oldbalance = "0.00";
                                    Long systemtime = System.currentTimeMillis();
                                    DecimalFormat df = new DecimalFormat("0.00");
                                    //修改用户余额
                                    if(datainfoDetail!=null){
                                        MlccUserInfo userInfo = userservice.queryUserinfoByusername(datainfoDetail.getUserId(),0);
                                        if(userInfo!=null){
                                            oldbalance = userInfo.getAccountBalance();
                                            //赋值新的余额
                                            double newbalance = Double.parseDouble(oldbalance)+Double.parseDouble(datainfoDetail.getMoney());
                                            userservice.update_user_balance(df.format(newbalance),userInfo.getId().toString());
                                            //插入财务流水表
                                            userservice.insert_financial(userInfo.getId().toString(),"FINA"+systemtime,"前端用户充值",datainfoDetail.getMoney(),
                                                    df.format(newbalance));
                                            //修改充值状态
                                            userservice.update_chargeOrder_status(datainfoDetail.getId().toString(),"1");
                                        }
                                    }
                                }
                                System.out.println("业务逻辑处理完成，支付完成");
                            } catch (Exception e) {
                                System.out.println("支付宝回调业务处理报错,params:" + paramsJson);
                            }
                        } else {
                            System.out.println("没有处理支付宝回调业务，支付宝交易状态：{},params:{}"+trade_status+"=="+paramsJson);
                        }
                    }
                });
                // 如果签名验证正确，立即返回success，后续业务另起线程单独处理
                // 业务处理失败，可查看日志进行补偿，跟支付宝已经没多大关系。
                //关闭线程池
                executorService.shutdown();
                return "success";
            } else {
                System.out.println("fail");
                System.out.println("支付宝回调签名认证失败，signVerified=false, paramsJson:{}"+paramsJson);
                return "failure";
            }
        } catch (AlipayApiException e) {
            System.out.println("fail");
            System.out.println("支付宝回调签名认证失败，signVerified=false, paramsJson:{}"+paramsJson);
            return "failure";
        }
    }


    // 将request中的参数转换成Map
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<String, String>();
        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;
            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }
        return retMap;
    }

    private AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
        String json = JSON.toJSONString(params);
        return JSON.parseObject(json, AlipayNotifyParam.class);
    }

    /**
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
     * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
     * 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
     * @param params
     * @throws AlipayApiException
     */
    private void check(Map<String, String> params) throws AlipayApiException {
        String outTradeNo = params.get("out_trade_no");

        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
//        Order order = getOrderByOutTradeNo(outTradeNo); // 这个方法自己实现
//        if (order == null) {
//            throw new AlipayApiException("out_trade_no错误");
//        }

        // 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
//        long total_amount = new BigDecimal(params.get("total_amount")).multiply(new BigDecimal(100)).longValue();
//        if (total_amount != order.getPayPrice().longValue()) {
//            throw new AlipayApiException("error total_amount");
//        }

        // 3、校验通知中的seller_id（或者seller_email)是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
        // 第三步可根据实际情况省略

        // 4、验证app_id是否为该商户本身。
//        if (!params.get("app_id").equals(alipayConfig.getAppid())) {
//            throw new AlipayApiException("app_id不一致");
//        }
    }

}
